package basicx.functionx
/*
# -*- coding:utf-8 -*-
* @Author  : ygree 
* @Time    : 2021/6/21 1:37
* @Software : IntelliJ IDEA
*
*/
/*为什么要在代码中使用函数类型?函数类型能让开发者少写模式化代码，写出更灵活的代码。
    Java8支持面向对象编程和lambda表达式，但不支持将函数作为参数传给
    另一个函数或变量，不过Java的替代方案是匿名内部类

    减小开销-->使用内联(复制代码到运行位置)
*/

/*
    lambda可以让你更灵活地编写应用，但是，灵活也是要付出代价的。
        在JVM上(你定义的lambda会以对象实例的形式存在NJVM会为所有同lambda打交道的变量分配内存，这就产生了内存开销。
        更糟的是，lambda的内存开销你带来性能问题。
    幸运的是，kotlin有一种优化机制叫内联，JVM就不需要使用lambda对象实例了，因而避免了变量内存分配。哪里需要使用lambda，编译器就会将函数体复制粘贴到哪里。
    使用lambda的递归函数无法内联，因为会导致复制粘贴无限循环，编译会发出警告。
*/
// C语言  预编译 宏定义,宏替换  #define MAX

//Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types
private inline fun add(a: Int, b: Int): Int {
    return a + b
}

private inline fun add(a: Int, b: Int, handle: (a: Int, b: Int) -> Int): Int {
    return handle(a, b)
}

private inline fun initInline(myFun: () -> Unit, nxtFun: () -> Unit) {
    myFun()
    println("initInline inner")
    nxtFun()
}

private inline fun crossinline(crossinline myFun: () -> Unit, nxtFun: () -> Unit) {
    myFun()
    println("crossinline inner")
    nxtFun()
}

private inline fun noinline(myFun: () -> Unit, noinline nxtFun: () -> Unit) {
    myFun()
    println("noinline inner")
    nxtFun()
}

private fun basic() {
    println("add ${add(1, 2)}")
    println(
        "add ${
            add(1, 2) { a, b ->
                a * b
            }
        }"
    )
    println("-------initInline--------")
    initInline({ println("initInline 1") }, { println("initInline 2") })
    println("------initInline---------")
    initInline({
        println("initInline 1")
        return // 加个return //整个函数被return
    }, { println("initInline 2") })
    println("------initInline-end--------")

}

private fun ads() {
//    要防止从lambda表达式和内联函数本身返回
    println("------crossinline---------")
    crossinline({
        println("crossinline 1")
        return@crossinline // ok
        println("crossinline 1 1")

//        return // err
    }, { println("crossinline 2") })
    println("------noinline---------")
//    如果内联函数不包含noinline函数参数且没有reified类型参数
    noinline({
        println("noinline 1")
//        return@crossinline // ok
//        return // err
    }, { println("noinline 2") })

}

private  fun main() {
    basic()
    ads()

}